package com.lemon.cloud.datascope.handler;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.extension.plugins.handler.DataPermissionHandler;
import com.lemon.cloud.datascope.annotation.DataColumn;
import com.lemon.cloud.datascope.annotation.DataScope;
import com.lemon.cloud.datascope.enums.ScopeType;
import com.lemon.cloud.datascope.sqlFilter.OrgScopeSqlFilter;
import com.lemon.cloud.security.model.SecurityUser;
import com.lemon.cloud.security.util.SecurityUtils;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.AnnotationUtils;

import java.lang.reflect.Method;

/**
 * @author HuangDS
 */
@Slf4j
public class DataScopeHandler implements DataPermissionHandler {

    @Autowired
    private OrgScopeSqlFilter orgScopeSqlFilter;

    /**
     * @param where             待执行 SQL Where 条件表达式
     * @param mappedStatementId Mybatis MappedStatement Id 根据该参数可以判断具体执行方法
     * @return
     */
    @Override
    public Expression getSqlSegment(Expression where, String mappedStatementId) {
        try {
            log.info("dataScope come in");
            Class<?> clazz = Class.forName(mappedStatementId.substring(0, mappedStatementId.lastIndexOf(StrUtil.DOT)));
            String methodName = mappedStatementId.substring(mappedStatementId.lastIndexOf(StrUtil.DOT) + 1);
            Method method = ReflectUtil.getMethodByName(clazz, methodName);
            if (method == null) {
                return where;
            }
            DataScope annotation = AnnotationUtils.findAnnotation(method, DataScope.class);
            if (annotation == null) {
                return where;
            }
            SecurityUser user = SecurityUtils.getUser();
            if (ObjectUtil.isNull(user) ||
                    ObjectUtil.isNull(user.getSysUser()) ||
                    ObjectUtil.isNull(user.getSysUser().getId())) {
                return where;
            }
            DataColumn[] dataColumns = annotation.value();
            if (ObjectUtil.isNull(dataColumns) || dataColumns.length == 0) {
                return where;
            }
            return doSQLFilter(dataColumns, where, user);
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return where;
    }

    private Expression doSQLFilter(DataColumn[] dataColumns, Expression where, SecurityUser user) {
        for (DataColumn column : dataColumns) {
            if (isOrgScope(column.scopeType())) {
                where = orgScopeSqlFilter.calcScope(column, where, user);
            }
        }
        return where;
    }

    public boolean isOrgScope(ScopeType scopeType) {
        return ScopeType.ORG.getType() == scopeType.getType();
    }

}
